package com.bidevalution.service.impl;

import com.bidevalution.core.constant.LocalPathConstant;
import com.bidevalution.core.enums.FileTypeEnum;
import com.bidevalution.dao.ApiBidFileMapper;
import com.bidevalution.service.ZbFileService;
import com.bidevalution.core.enums.ApiEnum;
import com.bidevalution.core.Common;
import com.bidevalution.core.enums.FileStatusEnum;
import com.bidevalution.core.util.HttpClientUtil;
import com.bidevalution.dao.ApiSectionInfoMapper;
import com.bidevalution.model.SectionInfo;
import com.qtp.core.common.HttpTookit;
import com.qtp.core.model.Response;
import com.qtp.core.util.DateUtil;
import com.qtp.core.util.OConvertUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author huyiqi
 * @date 2019/11/11
 */
@Service(value = "zbFileService")
public class ZbFileServiceImpl extends BaseServiceImpl implements ZbFileService {

    private static final Logger log = LoggerFactory.getLogger(ZbFileServiceImpl.class);
    private static final Pattern timePattern = Pattern.compile("\\..*\\+");
    /**
     * 从建易获取项目信息，再从T9获取招标文件
     * @return 返回结果
     */
    @SuppressWarnings("unchecked")
    @Override
    public Response<List<Map<String, Object>>> getTenderList() throws Exception {
        ApiEnum api = ApiEnum.GET_BIDDING_TENDER;
        String token = api.getToken();
        Map<String, Object> resultMap = invokeJyWebServiceWithGbkResult(api, token);
        if(resultMap != null) {
            Response<Map<String, Object>> execResult = jYApiSuccess(resultMap);
            if(execResult.isSuccess()) {
                List<Map<String, Object>> tenders;

                if(execResult.getResult().get("Tender") instanceof Map) {
                    tenders = new ArrayList<>();
                    Map<String, Object> map = (Map<String, Object>) execResult.getResult().get("Tender");
                    tenders.add(map);
                } else {
                    tenders = (List<Map<String, Object>>) execResult.getResult().get("Tender");
                }
                return Response.ok(tenders);
            } else {
                return Response.fail(execResult.getError());
            }
        }
        return Response.fail("接口返回值为空");
    }
    /**
     * 下载招标文件（xml和pdf）
     * @param tender 接口获取到的标段信息
     * @return 返回是否成功
     */
    @Override
    public Response<String> downloadTenderFiles(Map<String, Object> tender) throws Exception {
        if(tender != null) {
            SectionInfo sectionInfo = getSection(tender);
            String sectionId = sectionInfo.getSeqId();
            String sectionCode = sectionInfo.getSectionCode();

            ApiEnum api = ApiEnum.GET_PRO_FILE;
            String token = api.getToken();
            Map<String, String> params = new HashMap<>(4);
            params.put("code", sectionCode);
            params.put("token", token);
            Map<String, Object> resultMap = invokeHttpApi(api, params);
            if(resultMap != null) {
                Response<String> execResult = t9ApiSuccess(resultMap);
                if(!execResult.isSuccess()) {
                    return execResult;
                }
                String xmlUrl = OConvertUtils.getString(resultMap.get("projXmlUrl"));
                String pdfUrl = OConvertUtils.getString(resultMap.get("bidUrl"));
                xmlUrl = switchT9DownloadUrl(xmlUrl);
                pdfUrl = switchT9DownloadUrl(pdfUrl);
                Response<String> xmlRsp = downloadXml(xmlUrl, sectionCode, sectionInfo);
                Response<String> pdfRsp = downloadPdf(pdfUrl, sectionInfo);
                if(xmlRsp.isSuccess() && pdfRsp.isSuccess()) {
                    return Response.ok(sectionId);
                } else {
                    return  Response.fail(xmlRsp.getError() + pdfRsp.getError());
                }
            } else {
                return Response.fail("获取文件信息失败");
            }
        }
        return Response.fail("标段信息为空");
    }

    /**
     * 返回招标文件导入的结果
     * @param sectionCode 标段编码
     * @param result 结果：0失败，1成功
     * @param description 文字描述
     * @return 返回调用结果
     */
    @Override
    public Response<String> backZbFileStatus(String sectionCode, String result, String description) throws Exception {
        ApiEnum api = ApiEnum.BACK_TENDERING_DOCUMENTS;
        String token = api.getToken();
        Map<String, Object> resultMap = invokeJyWebService(api, token, sectionCode, result, description);
        return returnExecResult(resultMap, API_TYPE_JY);
    }

    /**
     * 下载招标xml文件
     * @param xmlUrl 文件url
     * @param sectionCode 标段编码
     * @param sectionInfo 标段信息
     * @return 返回下载结果
     * @throws IOException 调用接口时可能报错
     */
    private Response<String> downloadXml(String xmlUrl, String sectionCode, SectionInfo sectionInfo) throws IOException {
        int tenderFileState = sectionInfo.getTenderFileState();
        //判断是否需要下载xml
        if(tenderFileState == FileStatusEnum.NOT_DOWNLOAD.getStatus()) {
            //下载
            Response<String> xmlRsp = Common.downLoadXml(xmlUrl, sectionCode, LocalPathConstant.ZB_FILE_PATH);
            if(!xmlRsp.isSuccess()){
                return Response.fail("获取招标xml失败："+xmlRsp.getError());
            } else {
                //获取文件存放路径和文件名
                String path = xmlRsp.getResult();
                String fileName = Common.getFileNameByPath(path);
                int status = FileStatusEnum.DOWNLOAD_SUCCESS.getStatus();
                //保存文件操作信息（提供给解析服务用）
                saveBidFile(fileName, path, UUID.randomUUID().toString(), FileTypeEnum.ZB.getType(), sectionCode, status, bidFileMapper);
                //更新xml下载状态
                sectionInfo.setTenderFileState(FileStatusEnum.DOWNLOAD_SUCCESS.getStatus());
                beSectionInfoMapper.update(sectionInfo);
            }
        }
        return Response.ok();
    }

    /**
     * 获取标段信息
     * @param tender 接口获取到的单个标段信息
     * @return 返回标段信息
     */
    private SectionInfo getSection(Map<String, Object> tender) {
        String sectionCode = OConvertUtils.getString(tender.get("TenderNo"));
        String sectionName = OConvertUtils.getString(tender.get("TenderName"));
        String bidOpenTime = OConvertUtils.getString(tender.get("StartTime"));
        String bidOpenAddress = OConvertUtils.getString(tender.get("PlaceName"));
        //先获取，不存在再新增
        SectionInfo sectionInfo = beSectionInfoMapper.getSectionInfoByCode(sectionCode);
        if(sectionInfo == null) {
            sectionInfo = new SectionInfo();
            sectionInfo.setSeqId(UUID.randomUUID().toString());
            sectionInfo.setSectionCode(sectionCode);
            sectionInfo.setSectionName(sectionName);
            sectionInfo.setBidOpenTime(formatDate(bidOpenTime));
            sectionInfo.setBidOpenAddress(bidOpenAddress);
            sectionInfo.setTenderFileState(FileStatusEnum.NOT_DOWNLOAD.getStatus());
            beSectionInfoMapper.insert(sectionInfo);
        }

        return sectionInfo;
    }

    /**
     * 将yyyy-MM-dd'T'HH:mm:ssXXX格式的字符串转换为date对象
     * @param dateStr 时间字符串
     * @return 返回转换好的时间
     */
    private Date formatDate(String dateStr) {
        Matcher matcher = timePattern.matcher(dateStr);
        String format;
        if(matcher.find()) {
            format = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
        } else {
            format = "yyyy-MM-dd'T'HH:mm:ssXXX";
        }
        return DateUtil.stringToDate(dateStr, format);
    }


    /**
     * 下载招标pdf文件
     * @param url 下载的url
     * @return 返回下载结果
     * @throws IOException
     */
    private Response<String> downloadPdf(String url, SectionInfo sectionInfo) {
        if(StringUtils.isNotBlank(sectionInfo.getTenderFileMd5())) {
            return Response.ok();
        }
        if(StringUtils.isBlank(url)) {
            log.error("招标pdf文件路径为空");
            return Response.fail("招标pdf文件路径为空");
        }
        String businessId = null;
        //下载文件
        Map<String, byte[]> result = HttpClientUtil.getRemoteFileBytes(url);
        Set<Map.Entry<String, byte[]>> entries = result.entrySet();
        if(entries.size() > 0) {
            //获取文件名和流
            Map.Entry<String, byte[]> entry = entries.iterator().next();
            String fileName = entry.getKey();
            byte[] binary = entry.getValue();
            //上传的路径
            String fileServer = Common.spliceUrl(LocalPathConstant.FILE_SERVER_URL,"fileUploadController/uploadWholeFile.do");
            InputStream is = null;
            try {
                is = new ByteArrayInputStream(binary);
                businessId = HttpTookit.sendPostInputstream(fileServer, is, fileName, null);
            } catch (Exception e) {
                log.error("上传招标pdf时出错：", e);
            } finally {
                if(is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        log.error("关闭流时出错", e);
                    }
                }
            }
        } else {
            return Response.fail("无法下载招标pdf文件");
        }
        if(StringUtils.isNotBlank(businessId)) {
            sectionInfo.setTenderFileMd5(businessId);
            beSectionInfoMapper.update(sectionInfo);
            return Response.ok();
        } else {
            return Response.fail("pdf文件上传到mongo时出错");
        }
    }

    private String switchT9DownloadUrl(String url) {
        if(StringUtils.isNotBlank(LocalPathConstant.T9_FILE_SERVER_URL)
                && StringUtils.isNotBlank(LocalPathConstant.PROXY_T9_FILE_SERVER_URL)) {
            url = url.replace(LocalPathConstant.T9_FILE_SERVER_URL, LocalPathConstant.PROXY_T9_FILE_SERVER_URL);
        }
        return url;
    }

    @Autowired(required = false)
    private ApiSectionInfoMapper beSectionInfoMapper;
    @Autowired(required = false)
    private ApiBidFileMapper bidFileMapper;
}
